//main.c
#include "main.h"

struct decl * parser_root;


char * descape ()
{
// indexes input and output separately, but i >= j, never less
// so if the original string fits, then the de-escaped string will also. 

  char * unescaped  = strdup(yytext);
  char * result = strdup(yytext);
  
  int strlength = strlen( unescaped);
  int strlength2 = strlen( yytext);

  int i,j = 0; //unescaped i, result : j
  while (i < strlength)
  {
    int jFlag = 1;
    if (unescaped[i] == '\\')
    {
      //checks for escaped characters
      i++;
      if (unescaped[i] == 'n')
      {        result[j] = '\n';      }

      else if (unescaped[i] == '0')
      {        result[j] = '\0';     }

      else if (unescaped[i] == '\"')
      {        result[j] = '\"';      }
      
      else
      {        result[j] = unescaped[i];      }
    }
    else if ((unescaped[i] == '\"' || unescaped[i] == '\'') && (i==0 || i==strlength-1) )
    {
      //checks for the beginning and ending quotes
      jFlag = 0;
    }
    else 
    {
      //default case, just copy the char over
      result[j] = unescaped[i];
    }
    i++;
    if (jFlag) j++;
  } //endwhile over stringlength
  result[j] = '\0';
  free(unescaped);
  //calling fn must free(result) after done using it
  return result;
} //endfunc


int main( int argc, char * argv[])
{
  int doParse     = 0;
  int doScan      = 0;
  int doPrint     = 0;
  int doTypecheck = 0;
  int doResolve   = 0;
  int doResolvePrint   = 0;
  int doCodegen = 0;
  parser_root = decl_create("", 0, 0, 0, 0, 0, 0);

  if ( argc == 3 || argc == 4 )
  {
    if (strncmp(argv[1], "-parse", 6) == 0) 
    {
      doParse = 1;
    } else if (strncmp(argv[1], "-scan", 5) == 0) 
    {
      doScan = 1;
    } else if (strncmp(argv[1], "-print", 6) == 0) 
    {
      doPrint = 1;
      doParse = 1;
    } else if (strncmp(argv[1], "-resolve", 8) == 0) 
    {
      doResolve = 1;
      doResolvePrint = 1;
      doParse = 1;
    } else if ((strncmp(argv[1], "-typecheck", 10) == 0) ||
               (strncmp(argv[1], "-t"        ,  2) == 0) )
    {
      doResolve = 1;
      doParse = 1;
      doTypecheck = 1;
    } else if (((strncmp(argv[1], "-codegen", 10) == 0) || (strncmp(argv[1], "-c", 2) == 0) ) 
                  && argc ==4)
    {
      char * outfilename = strdup(argv[3]);
      doResolve = 1;
      doParse = 1;
      doTypecheck = 1;
      doCodegen = 1;
    } else 
    {
      printf("usage: %s -[scan|parse|print|resolve|typecheck|codegen] SOURCE [DEST]\n", argv[0]);
      return 0;
    }
    yyin = fopen( argv[2], "r" );
  }
  else
  {
    printf("usage: %s -[scan|parse|print|resolve|typecheck|codegen] SOURCE [DEST]\n", argv[0]);
    return 0;
  }
  
  if (doScan)
  {
    scan();
  } 
  if (doParse)
  {
    if( yyparse()==0)
    { 
     // printf("parse good\n");
    } else {
      printf("parse failed\n");
    }
  } //end parsing

  if (doPrint)
  {
    decl_print(parser_root);   
  }

  if (doResolve)
  {
    decl_resolve(parser_root, doResolvePrint);   
  }
  if (doTypecheck)
  {
    decl_typecheck(parser_root);   
  }
  if (doCodegen)
  {
    decl_codegen(parser_root);
  }
  return 0;
} //endfunc


void scan()
{
  //start scanning;
  int t;
  while ( t = yylex() )
  {     
    char * result = descape();  //'member to free later
    if (t == EOF) break;
    switch (t)
    {
      case TOKEN_STRING_LITERAL:
        printf("\nSTRING_LITERAL %s ", result);
        continue;
        break;
      
      case TOKEN_CHARACTER_LITERAL:
        printf("\nCHARACTER_LITERAL %s", result);
        continue;
        break;
        
      case TOKEN_INTEGER_LITERAL:
        printf("\nINTEGER_LITERAL");
        continue;
        break;
      
      case TOKEN_GE:
        printf("\nGE ");
        continue;
        break;      

      case TOKEN_LE:
        printf("\nLE ");
        continue;
        break;      
        
      case TOKEN_GT:
        printf("\nGT ");
        continue;
        break;      

      case TOKEN_LT:
        printf("\nLT ");
        continue;
        break;      
      
      case TOKEN_EQ:
        printf("\nEQ ");
        continue;
        break;      
      
      case TOKEN_NE:
        printf("\nNE ");
        continue;
        break;      
        
      case TOKEN_IDENTIFIER:
        printf("\nIDENTIFIER ");
        continue;
        break;        

      case TOKEN_COMMA:
        printf("\nCOMMA ");
        continue;
        break; 
      
      case TOKEN_SEMICOLON:
        printf("\nSEMICOLON ");
        continue;
        break; 
      
      case TOKEN_ASSIGN:
        printf("\nASSIGNMENT ");
        continue;
        break;        

      case TOKEN_INTEGER:
        printf("\nINTEGER ");
        continue;
        break;
      
      case TOKEN_BOOLEAN:
        printf("\nBOOLEAN ");
        continue;
        break;
      
      case TOKEN_CHAR:
        printf("\nCHAR ");
        continue;
        break;
      
      case TOKEN_STRING:
        printf("\nSTRING ");
        continue;
        break;      

      case TOKEN_TRUE:
        printf("\nTRUE ");
        continue;
        break;
      
      case TOKEN_FALSE:
        printf("\nFALSE ");
        continue;
        break;

      case TOKEN_IF:
        printf("\nIF ");
        continue;
        break;
      
      case TOKEN_WHILE:
        printf("\nWHILE ");
        continue;
        break;
      
      case TOKEN_RETURN:
        printf("\nRETURN ");
        continue;
        break;
      
      case TOKEN_ELSE:
        printf("\nELSE ");
        continue;
        break;
      
      case TOKEN_VOID:
        printf("\nVOID ");
        continue;
        break;
      
      case TOKEN_PRINT:
        printf("\nPRINT ");
        continue;
        break;          
      
      case TOKEN_LOGICALAND:
        printf("\nLOGICALAND ");
        continue;
        break;
      
      case TOKEN_LOGICALOR:
        printf("\nLOGICALOR ");
        continue;
        break;

      case TOKEN_OPENPAREN:
        printf("\nOPENPAREN ");
        continue;
        break;
      
      case TOKEN_CLOSEPAREN:
        printf("\nCLOSEPAREN ");
        continue;
        break;
      
      case TOKEN_OPENCURLY:
        printf("\nOPENCURLY ");
        continue;
        break;
      
      case TOKEN_CLOSECURLY:
        printf("\nCLOSECURLY ");
        continue;
        break;      
        
      case TOKEN_STAR:
        printf("\nSTAR ");
        continue;
        break;
      
      case TOKEN_SLASH :
        printf("\nSLASH ");
        continue;
        break;
      
      case TOKEN_PERCENT:
        printf("\nPERCENT ");
        continue;
        break;
      
      case TOKEN_PLUS:
        printf("\nPLUS ");
        continue;
        break;
      
      case TOKEN_MINUS:
        printf("\nMINUS ");
        continue;
        break;
      
      case TOKEN_CARET:
        printf("\nCARET ");
        continue;
        break;

      case TOKEN_INCREMENT:
        printf("\nINCREMENT ");
        continue;
        break;

      case TOKEN_DECREMENT:
        printf("\nDECREMENT ");
        continue;
        break;

      case TOKEN_ERROR:
      default:      
        fprintf(stderr, "SCAN ERROR: %s is not valid\n", yytext);
        exit(1);

      } //end switch
    
    free(result);    

    fflush(stdout);
    fflush(stderr);
    fprintf(stderr, "SCAN ERROR: %s is not valid\n", yytext);
    exit(1);
     
  } //endwhile  

}
